package com.hzzftech.watchdog.busi.controller;

import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

import com.hzzftech.watchdog.busi.constants.BusiConstant;
import com.hzzftech.watchdog.busi.core.file.repository.FileRepositoryManager;
import com.hzzftech.watchdog.busi.core.file.repository.KtFileRepositoryFileParser;
import com.hzzftech.watchdog.busi.domain.KtDispatcher;
import com.hzzftech.watchdog.busi.domain.KtFileRepositoryMsg;
import com.hzzftech.watchdog.busi.domain.KtFileVersion;
import com.hzzftech.watchdog.busi.service.IKtDispatcherService;
import com.hzzftech.watchdog.busi.service.IKtFileRepositoryMsgService;
import com.hzzftech.watchdog.busi.service.IKtFileVersionService;
import com.hzzftech.watchdog.busi.utils.FileUtils;
import com.hzzftech.watchdog.busi.utils.ZipUtil;
import com.hzzftech.watchdog.common.core.text.Convert;
import com.hzzftech.watchdog.common.utils.ShiroUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.hzzftech.watchdog.common.annotation.Log;
import com.hzzftech.watchdog.common.enums.BusinessType;
import com.hzzftech.watchdog.busi.domain.KtFileRepository;
import com.hzzftech.watchdog.busi.service.IKtFileRepositoryService;
import com.hzzftech.watchdog.common.core.controller.BaseController;
import com.hzzftech.watchdog.common.core.domain.AjaxResult;
import com.hzzftech.watchdog.common.utils.poi.ExcelUtil;
import com.hzzftech.watchdog.common.core.page.TableDataInfo;

import javax.servlet.http.HttpServletResponse;

/**
 * 文件资源库Controller
 * 
 * @author kt-watchdog
 * @date 2021-12-09
 */
@Controller
@RequestMapping("/busi/file/repository")
public class KtFileRepositoryController extends BaseController
{
    private String prefix = "busi/file/repository";

    @Autowired
    private IKtFileRepositoryService ktFileRepositoryService;

    @Autowired
    private IKtFileRepositoryMsgService msgService;

    @Autowired
    private IKtFileVersionService versionService;

    @Autowired
    private IKtDispatcherService dispatcherService;

    @Value("${kt-watchdog.file_repository_location}")
    private String  FILE_REPOSITORY_LOCATION;

    @RequiresPermissions("busi:repository:view")
    @GetMapping()
    public String repository()
    {
        return prefix + "/repository";
    }

    @GetMapping("/detail/{id}")
    public String jumpDetail(@PathVariable("id") Long id, ModelMap mmap) {
        KtFileRepository ktFileRepository = ktFileRepositoryService.selectKtFileRepositoryById(id);
        // 文件资源仓库信息
        mmap.addAttribute("repo", ktFileRepository);

        // 解析资源仓库文件夹
        FileRepositoryManager manager = new FileRepositoryManager(
                FILE_REPOSITORY_LOCATION,
                ktFileRepository.getDirectory(),
                new KtFileRepositoryFileParser(msgService,versionService, id, FILE_REPOSITORY_LOCATION));
        manager.parse();

        return "busi/file/msg/msg";
    }

    /**
     * 查询文件资源库列表
     */
    @RequiresPermissions("busi:repository:list")
    @PostMapping("/list")
    @ResponseBody
    public TableDataInfo list(KtFileRepository ktFileRepository)
    {
        startPage();
        List<KtFileRepository> list = ktFileRepositoryService.selectKtFileRepositoryList(ktFileRepository);
        return getDataTable(list);
    }

    /**
     * 导出文件资源库列表
     */
    @RequiresPermissions("busi:repository:export")
    @Log(title = "文件资源库", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    @ResponseBody
    public AjaxResult export(KtFileRepository ktFileRepository)
    {
        List<KtFileRepository> list = ktFileRepositoryService.selectKtFileRepositoryList(ktFileRepository);
        ExcelUtil<KtFileRepository> util = new ExcelUtil<KtFileRepository>(KtFileRepository.class);
        return util.exportExcel(list, "文件资源库数据");
    }

    @RequiresPermissions("busi:repository:export")
    @Log(title = "文件资源库到处ZIP包", businessType = BusinessType.EXPORT)
    @GetMapping("/exportRepo/{repoId}")
    public void exportRepo(@PathVariable("repoId") Long repoId, HttpServletResponse response) {
        response.setContentType("application/octet-stream");
        response.setCharacterEncoding("utf-8");
        KtFileRepository ktFileRepository = ktFileRepositoryService.selectKtFileRepositoryById(repoId);
        response.addHeader("Content-Disposition", "attachment;filename=" + ktFileRepository.getDirectory()+".zip");
        if (ktFileRepository != null) {
            File repof = new File(FILE_REPOSITORY_LOCATION + File.separator + ktFileRepository.getDirectory());
            if (repof.exists() && repof.isDirectory()) {
                try {
                    ZipUtil.toZip(repof.getAbsolutePath(), response.getOutputStream(), true);
                } catch (IOException e) {
                    logger.error("导出失败资源仓库失败", e);
                }
            }
        }
    }

    /**
     * 新增文件资源库
     */
    @GetMapping("/add")
    public String add()
    {
        return prefix + "/add";
    }

    /**
     * 新增保存文件资源库
     */
    @RequiresPermissions("busi:repository:add")
    @Log(title = "文件资源库", businessType = BusinessType.INSERT)
    @PostMapping("/add")
    @ResponseBody
    public AjaxResult addSave(KtFileRepository ktFileRepository)
    {
        ktFileRepository.setCreatedBy(ShiroUtils.getUserId());
        ktFileRepository.setCreatedTime(new Date());
        if (!ktFileRepositoryService.selectDirectoryUnique(-1L,ktFileRepository.getDirectory()).isEmpty()) {
            return AjaxResult.error("文件夹已存在【"+ktFileRepository.getDirectory()+"】");
        }
        return toAjax(ktFileRepositoryService.insertKtFileRepository(ktFileRepository));
    }

    /**
     * 修改文件资源库
     */
    @RequiresPermissions("busi:repository:edit")
    @GetMapping("/edit/{id}")
    public String edit(@PathVariable("id") Long id, ModelMap mmap)
    {
        KtFileRepository ktFileRepository = ktFileRepositoryService.selectKtFileRepositoryById(id);
        mmap.put("ktFileRepository", ktFileRepository);
        return prefix + "/edit";
    }

    /**
     * 修改保存文件资源库
     */
    @RequiresPermissions("busi:repository:edit")
    @Log(title = "文件资源库", businessType = BusinessType.UPDATE)
    @PostMapping("/edit")
    @ResponseBody
    public AjaxResult editSave(KtFileRepository ktFileRepository)
    {
        List<KtFileRepository> ktFileRepositories = ktFileRepositoryService.selectDirectoryUnique(ktFileRepository.getId(), ktFileRepository.getDirectory());
        if (ktFileRepositories.size() > 0) {
            return AjaxResult.error("文件夹已存在【"+ktFileRepository.getDirectory()+"】");
        }

        ktFileRepository.setUpdatedBy(ShiroUtils.getUserId());
        ktFileRepository.setUpdatedTime(new Date());
        KtFileRepository ktFileRepository1 = ktFileRepositoryService.selectKtFileRepositoryById(ktFileRepository.getId());
        if (!ktFileRepository1.getDirectory().equals(ktFileRepository.getDirectory())) {
            KtDispatcher dispatcher = new KtDispatcher();
            dispatcher.setRepositoryId(ktFileRepository.getId());
            List<KtDispatcher> ktDispatchers = dispatcherService.selectKtDispatcherList(dispatcher);
            if (ktDispatchers.size() > 0) {
                return AjaxResult.error("文件资源库【"+ktFileRepository.getName()+"】已被调度引用，不能修改文件夹");
            }

            File file = new File(FILE_REPOSITORY_LOCATION + File.separator + ktFileRepository1.getDirectory());
            if (file.exists()) {
                file.renameTo(new File(FILE_REPOSITORY_LOCATION + File.separator +ktFileRepository.getDirectory()));
                KtFileRepositoryMsg msg = new KtFileRepositoryMsg();
                msg.setParentId(0L);
                msg.setfRepoId(ktFileRepository.getId());
                List<KtFileRepositoryMsg> ktFileRepositoryMsgs = msgService.selectKtFileRepositoryMsgList2(msg);
                if (ktFileRepositoryMsgs.size() == 1) {
                    ktFileRepositoryMsgs.get(0).setFileName(ktFileRepository.getDirectory());
                    msgService.updateKtFileRepositoryMsg(ktFileRepositoryMsgs.get(0));
                } else {
                    return AjaxResult.error("资源库文件出现异常，请联系管理员，ID【"+ktFileRepository.getId()+"】");
                }
            }
        }

        return toAjax(ktFileRepositoryService.updateKtFileRepository(ktFileRepository));
    }

    /**
     * 删除文件资源库
     */
    @RequiresPermissions("busi:repository:remove")
    @Log(title = "文件资源库", businessType = BusinessType.DELETE)
    @PostMapping( "/remove")
    @ResponseBody
    public AjaxResult remove(String ids)
    {
        String[] strings = Convert.toStrArray(ids);

        int count = 0;
        for (String id : strings) {
            long _id = Long.parseLong(id);
            KtDispatcher dispatcher = new KtDispatcher();
            dispatcher.setRepositoryId(_id);
            List<KtDispatcher> list = dispatcherService.selectKtDispatcherList(dispatcher, BusiConstant.REPOSITORY_TYPE_FILE);
            if (list.size()> 0) {
                return AjaxResult.error("删除失败，有任务引用了该仓库");
            }

            // 删除文件资源库的版本文件
            KtFileRepository ktFileRepository = ktFileRepositoryService.selectKtFileRepositoryById(_id);
            FileUtils.deleteDirectory(FILE_REPOSITORY_LOCATION+File.separator+"version_"+ktFileRepository.getDirectory());

            // 删除文件资源库所有文件
            FileUtils.deleteDirectory(FILE_REPOSITORY_LOCATION+File.separator+ktFileRepository.getDirectory());
            msgService.deleteKtFileRepositoryMsgByRepoId(_id);

            // 删除文件资源库对应的数据库记录
            ktFileRepositoryService.deleteKtFileRepositoryById(_id);

            count++;
        }

        return toAjax(count);
    }
}
